// b03.v
// Verilog version, rewritten by Li Shen, Aug 2002
// Institute of Computing Technology, Chinese Academy of Sciences
// The original VHDL version is b03.vhd from Politecnico di Torino

module b03 (clock,reset,request1,request2,request3,request4,grant_o);
input clock;
input reset;
input request1;
input request2;
input request3;
input request4;
output [3:0] grant_o;
/////
wire clock;
wire reset;
wire request1;
wire request2;
wire request3;
wire request4;
reg [3:0] grant_o;
/////
parameter INIT=0, ANALISI_REQ=1, ASSIGN=2;
parameter U1=3'b100, U2=3'b010, U3=3'b001, U4=3'b111;
reg [1:0] stato;
reg [2:0] coda0,coda1,coda2,coda3;
reg ru1,ru2,ru3,ru4;
reg fu1,fu2,fu3,fu4;
reg [3:0] grant;
/////
always @(posedge clock)
begin
  if (reset)
  begin
    stato=INIT;
    coda0=3'b000; coda1=3'b000; coda2=3'b000; coda3=3'b000;
    ru1=0; ru2=0; ru3=0; ru4=0;
    fu1=0; fu2=0; fu3=0; fu4=0;
    grant=4'b0000;
    grant_o<=4'b0000;
  end
  else
    case (stato)
    INIT: begin
            ru1  = request1;
            ru2  = request2;
            ru3  = request3;
            ru4  = request4;
            stato= ANALISI_REQ;
	  end
    ANALISI_REQ: begin
		   grant_o<=grant;
                   if (ru1)
		   begin
		     if (!fu1)
		     begin
		       coda3 = coda2;
		       coda2 = coda1;
		       coda1 = coda0;
		       coda0 = U1;
		     end
		   end
                   else if (ru2)
		   begin
		     if (!fu2)
		     begin
		       coda3 = coda2;
		       coda2 = coda1;
		       coda1 = coda0;
		       coda0 = U2;
		     end
		   end
                   else if (ru3)
		   begin
		     if (!fu3)
        	     begin
		       coda3 = coda2;
		       coda2 = coda1;
		       coda1 = coda0;
		       coda0 = U3;
		     end
		   end
                   else if (ru4)
		   begin
		     if (!fu4)
		     begin
		       coda3 = coda2;
		       coda2 = coda1;
		       coda1 = coda0;
		       coda0 = U4;
		     end
		   end
		   fu1  = ru1;
		   fu2  = ru2;
		   fu3  = ru3;
		   fu4  = ru4;
                   stato= ASSIGN;
		 end
    ASSIGN: begin
              if (fu1 || fu2 || fu3 || fu4)
	      begin
		case (coda0)
		U1:	 grant=4'b1000;
		U2:	 grant=4'b0100;
		U3:	 grant=4'b0010;
		U4:	 grant=4'b0001;
		default: grant=4'b0000;
		endcase
 		coda0=coda1;
		coda1=coda2;
		coda2=coda3;
		coda3=3'b000;
	      end
	      ru1  = request1;
	      ru2  = request2;
	      ru3  = request3;
	      ru4  = request4;
	      stato= ANALISI_REQ;
	    end
    endcase
end
endmodule
